package com.planw.beetl.sql.search;

import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiTypeParameterListOwner;
import com.intellij.util.Processor;
import com.intellij.util.QueryParameters;
import com.planw.beetl.utils.JavaService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

/**
 * 通过Ctrl+左键点击mapper方法跳转md文件
 */
public class BeetlSqlJavaMapperQueryExecutorBase extends
    QueryExecutorBase<PsiElement, QueryParameters> {


  protected void toSearchSql(PsiClass psiClass, PsiMethod psiMethod,
      Processor<? super PsiElement> consumer) {

    JavaService javaService = JavaService.getInstance(psiClass.getProject());
    if (!psiClass.isInterface() || !javaService.checkIsBeetlSqlClass(psiClass)) {
      return;
    }
    PsiClassType[] classTypes = psiClass.getExtendsListTypes();
    String sqlFileName = null;
    for (PsiClassType classType : classTypes) {
      if (!classType.getInternalCanonicalText()
          .startsWith("org.beetl.sql.core.mapper.BaseMapper")) {
        continue;
      }
      sqlFileName = classType.getParameters()[0].getPresentableText();
    }
    if (StringUtils.isBlank(sqlFileName)) {
      return;
    }
    Map<String, PsiMethod> psiMethodMap = new HashMap<>();
    psiMethodMap.put(psiMethod.getName(), psiMethod);

    List<PsiFile> fileList = javaService.getAllBeetlSqlFiles(psiClass.getProject(), sqlFileName);
    if (fileList == null || fileList.isEmpty()) {
      return;
    }
    Map<String, List<PsiElement>> targetSqlElement = javaService
        .buildTargetPsiElement(fileList, psiMethodMap);
    if (targetSqlElement == null || targetSqlElement.isEmpty()) {
      return;
    }
    List<PsiElement> psiElements = targetSqlElement.get(psiMethod.getName());
    if (psiElements == null || psiElements.isEmpty()) {
      return;
    }
    for (PsiElement psiElement : psiElements) {
      consumer.process(psiElement);
    }

  }

  @Override
  public void processQuery(@NotNull QueryParameters queryParameters,
      @NotNull Processor<? super PsiElement> consumer) {

    if (!(queryParameters instanceof PsiTypeParameterListOwner)) {
      return;
    }
    if (!(queryParameters instanceof PsiMethod)) {
      return;
    }
    final Application application = ApplicationManager.getApplication();

    application.runReadAction(new Runnable() {

      @Override
      public void run() {

        PsiMethod psiMethod = (PsiMethod) queryParameters;
        PsiClass psiClass = psiMethod.getContainingClass();
        if (null == psiClass) {
          return;
        }
        toSearchSql(psiClass, psiMethod, consumer);
      }
    });
  }

}
